package com.fintech.third.service.predictmessage;

import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.RandomStringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.fintech.common.enums.RespStatus;
import com.fintech.common.service.BaseServiceImpl;
import com.fintech.common.util.ApiResponse;
import com.fintech.common.util.PropertiesUtils;
import com.fintech.third.constant.LocalStatus;
import com.fintech.third.constant.ThirdMethodConstants;
import com.fintech.third.dao.predictmessage.EdcMessagePredictInfoMapper;
import com.fintech.third.dao.predictmessage.EdcRiskModelMapper;
import com.fintech.third.model.predictmessage.EdcMessagePredictInfo;
import com.fintech.third.model.predictmessage.EdcRiskModel;
import com.fintech.third.model.predictmessage.PredictMessageQuery;
import com.fintech.third.utils.HttpUtil;
import com.marvels.common.utils.IdCarUtils;
import com.marvels.common.utils.MarvelsLogUtil;

import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;

@Service("predictMessageService")
public class PredictMessageServiceImpl extends BaseServiceImpl implements PredictMessageService{

	@Autowired
	private EdcMessagePredictInfoMapper edcMessagePredictInfoMapper;
	@Autowired
	private EdcRiskModelMapper edcRiskModelMapper;
	
	@Override
	public ApiResponse<EdcMessagePredictInfo> excutePredictMessage(Map<String, String> param) {
		MarvelsLogUtil.getInstance().info("短信模型评分，请求参数:" + param.toString());
		ApiResponse<EdcMessagePredictInfo> resp = new ApiResponse<EdcMessagePredictInfo>();
		//如果接口停用，直接返回（视具体情况，有的返回停用，有的返回相关值）
		if (PropertiesUtils.isTurnOffForSwitch("switch.msgpredict001")) {
			resp.setCode(RespStatus.DISABLE.getCode());
			resp.setMsg(RespStatus.DISABLE.getMsg());
			return resp;
		}
		
		String loanId = param.get("loanId"); // 查询的loanId
		String mobile = param.get("mobile"); //手机号
		String idCard = param.get("idCard");//身份证
		
		if(StrUtil.hasEmpty(loanId, mobile)){
			MarvelsLogUtil.getInstance().info("loanId[" + loanId + "]，短信模型评分，请求参数缺失");
			resp.setCodeAndMessage(RespStatus.ERROR.getCode(), "请求参数缺失");
			return resp;
		}
		
		//生成唯一编号
		String reqNo = System.currentTimeMillis() + "_" + RandomStringUtils.randomAlphanumeric(6);
		//相关记录变量声明
		Date sTime = new Date();//请求开始时间
		String responseCode = null;//第三方code
		String status = LocalStatus.REQUEST_FAIL.getCode();// 默认请求失败
		EdcMessagePredictInfo edcMessagePredictInfo = new EdcMessagePredictInfo();
		edcMessagePredictInfo.setReqNo(reqNo);
		edcMessagePredictInfo.setLoanId(loanId);
		edcMessagePredictInfo.setCode("F");
		try {
			String url = PropertiesUtils.getString("predict_message_url"); //请求url
			String haveMsgExcute = PropertiesUtils.getString("have_msg_excute"); //有短信才查询 
			
			// 如果当前loanId取得到数据就去当前loanId的，否则取复贷loanId的
			List<String> contentList = edcMessagePredictInfoMapper.queryMsgContetList(loanId);
			
			if((contentList == null || contentList.size() == 0) && Boolean.getBoolean(haveMsgExcute)){
				MarvelsLogUtil.getInstance().info("loanId[" + loanId + "]，短信模型评分，短信条数为0，不进行查询");
				resp.setCodeAndMessage(RespStatus.ERROR.getCode(), "短信条数为0，不进行查询");
				return resp;
			}
			
			//1.构建请求参数
			PredictMessageQuery predictMessageQuery = new PredictMessageQuery();
			predictMessageQuery.setLoanId(loanId);
			predictMessageQuery.setContents(contentList);
			//2.打印请求参数
			MarvelsLogUtil.getInstance().info("loanId[" + loanId + "]，短信模型评分，整体请求信息：" + JSONUtil.toJsonStr(predictMessageQuery));
			String result = HttpUtil.httpPost(url, com.alibaba.fastjson.JSONObject.toJSONString(predictMessageQuery));
			MarvelsLogUtil.getInstance().info("loanId[" + loanId + "]，短信模型评分，接口返回结果:" + result);
			if(StrUtil.isNotBlank(result)){
				try {
					status = LocalStatus.IN_DATABASE_FAIL.getCode();
					
					JSONObject jsonResult = JSONUtil.parseObj(result);
					edcMessagePredictInfo.setContentNumber(contentList.size());
					edcMessagePredictInfo.setTaskId(jsonResult.getStr("taskId"));
					edcMessagePredictInfo.setThirdCode(jsonResult.getStr("code"));
					edcMessagePredictInfo.setMsg(jsonResult.getStr("msg"));
					if(StrUtil.equals(edcMessagePredictInfo.getThirdCode(), "1")){
						//调用成功
						JSONObject data = jsonResult.getJSONObject("data");
						if(!data.isEmpty()){
							edcMessagePredictInfo.setProbability(data.getStr("probability"));
							edcMessagePredictInfo.setScore(data.getInt("score"));
						}
						edcMessagePredictInfo.setCode("S");
						status = LocalStatus.SUCCESS_WITH_DATA.getCode();
						resp.setCodeAndMessage(RespStatus.SUCCESS.getCode(), RespStatus.SUCCESS.getMsg());
					}else if(StrUtil.equals(edcMessagePredictInfo.getThirdCode(), "-1")){
						//-1 使用自定义范围值
						String noHaveMsgScoreMin = PropertiesUtils.getString("no_have_msg_score_min"); //最大分
						String noHaveMsgScoreMax = PropertiesUtils.getString("no_have_msg_score_max"); //最低分
						Integer score = RandomUtil.randomInt(Integer.parseInt(noHaveMsgScoreMin), Integer.parseInt(noHaveMsgScoreMax));
						edcMessagePredictInfo.setScore(score);
						edcMessagePredictInfo.setCode("S");
						status = LocalStatus.SUCCESS_WITH_DATA.getCode();
						resp.setCodeAndMessage(RespStatus.SUCCESS.getCode(), RespStatus.SUCCESS.getMsg());
					}else{
						//返回非成功状态
						status = LocalStatus.CALL_SUCCESS.getCode();
						resp.setCodeAndMessage(RespStatus.DEFAULT.getCode(), RespStatus.DEFAULT.getMsg());
					}
					edcMessagePredictInfoMapper.insertSelective(edcMessagePredictInfo);
					resp.setData(edcMessagePredictInfo);
				} catch (Exception e) {
					resp.setCodeAndMessage(RespStatus.DATABASE_ERROR.getCode(), RespStatus.DATABASE_ERROR.getMsg());
					MarvelsLogUtil.getInstance().error("loanId[" + loanId + "]，短信模型评分，数据落库发生异常", e);
				}
			}
		} catch(Exception e){
			resp.setCodeAndMessage(RespStatus.REQ_ERROR.getCode(), RespStatus.REQ_ERROR.getMsg());
			MarvelsLogUtil.getInstance().error("loanId[" + loanId + "]，短信模型评分，请求发生异常", e);
		}finally {
			saveDataQueryLogNew(reqNo, loanId, mobile, sTime, ThirdMethodConstants.MSGPREDICT001, responseCode,
					status, "edc_message_predict_query_log", idCard);
		}
		return resp;
	}

	@Override
	public ApiResponse<EdcRiskModel> excuteRiskModel(Map<String, Object> param) {
		MarvelsLogUtil.getInstance().info("风险模型，请求参数:" + JSONUtil.toJsonStr(param));
		ApiResponse<EdcRiskModel> resp = new ApiResponse<EdcRiskModel>();
		//如果接口停用，直接返回（视具体情况，有的返回停用，有的返回相关值）
		if (PropertiesUtils.isTurnOffForSwitch("switch.riskmodel001")) {
			resp.setCode(RespStatus.DISABLE.getCode());
			resp.setMsg(RespStatus.DISABLE.getMsg());
			return resp;
		}
		
		String loanId = StrUtil.utf8Str(param.get("loanId"));
		String mobile = StrUtil.utf8Str(param.get("mobile"));
		String idCard = StrUtil.utf8Str(param.get("cardNo"));
		if(StrUtil.hasEmpty(loanId, mobile)){
			MarvelsLogUtil.getInstance().info("loanId[" + loanId + "]，风险模型，请求参数缺失");
			resp.setCodeAndMessage(RespStatus.ERROR.getCode(), "请求参数缺失");
			return resp;
		}
		// 转化参数
		Map<String, Object> requestParam = parseParams(param);
		
		//生成唯一编号
		String reqNo = System.currentTimeMillis() + "_" + RandomStringUtils.randomAlphanumeric(6);
		//相关记录变量声明
		Date sTime = new Date();//请求开始时间
		String responseCode = null;//第三方code
		String status = LocalStatus.REQUEST_FAIL.getCode();// 默认请求失败
		EdcRiskModel edcMessagePredictInfo = new EdcRiskModel();
		edcMessagePredictInfo.setReqNo(reqNo);
		edcMessagePredictInfo.setLoanId(loanId);
		edcMessagePredictInfo.setCode("F");
		edcMessagePredictInfo.setParams(JSONUtil.toJsonStr(requestParam));
		try {
			String url = PropertiesUtils.getString("risk.model.url"); //请求url
			//1.构建请求参数
			//2.打印请求参数
			MarvelsLogUtil.getInstance().info("loanId[" + loanId + "]，风险模型，整体请求信息：" + JSONUtil.toJsonStr(requestParam));
			String result = HttpUtil.httpPost(url, com.alibaba.fastjson.JSONObject.toJSONString(requestParam));
			MarvelsLogUtil.getInstance().info("loanId[" + loanId + "]，风险模型，接口返回结果:" + result);
			if(StrUtil.isNotBlank(result)){
				try {
					status = LocalStatus.IN_DATABASE_FAIL.getCode();
					JSONObject jsonResult = JSONUtil.parseObj(result);
					edcMessagePredictInfo.setThirdCode(jsonResult.getStr("code"));
					edcMessagePredictInfo.setMsg(jsonResult.getStr("msg"));
					if(StrUtil.equals(edcMessagePredictInfo.getThirdCode(), "1")){
						//调用成功
						JSONObject data = jsonResult.getJSONObject("data");
						if(!data.isEmpty()){
							edcMessagePredictInfo.setProbability(data.getStr("probability"));
							edcMessagePredictInfo.setPrediction(data.getStr("prediction"));
						}
						edcMessagePredictInfo.setCode("S");
						status = LocalStatus.SUCCESS_WITH_DATA.getCode();
						resp.setCodeAndMessage(RespStatus.SUCCESS.getCode(), RespStatus.SUCCESS.getMsg());
					}else{
						//返回非成功状态
						status = LocalStatus.CALL_SUCCESS.getCode();
						resp.setCodeAndMessage(RespStatus.DEFAULT.getCode(), RespStatus.DEFAULT.getMsg());
					}
					edcRiskModelMapper.insertSelective(edcMessagePredictInfo);
					resp.setData(edcMessagePredictInfo);
				} catch (Exception e) {
					resp.setCodeAndMessage(RespStatus.DATABASE_ERROR.getCode(), RespStatus.DATABASE_ERROR.getMsg());
					MarvelsLogUtil.getInstance().error("loanId[" + loanId + "]，风险模型，数据落库发生异常", e);
				}
			}
		} catch(Exception e){
			resp.setCodeAndMessage(RespStatus.REQ_ERROR.getCode(), RespStatus.REQ_ERROR.getMsg());
			MarvelsLogUtil.getInstance().error("loanId[" + loanId + "]，风险模型，请求发生异常", e);
		}finally {
			saveDataQueryLogNew(reqNo, loanId, mobile, sTime, ThirdMethodConstants.RISKMODEL001, responseCode,
					status, "edc_risk_model_query_log", idCard);
		}
		return resp;
	}

	/**
	 * 转换参数
	 * @param param
	 * @return
	 * @author:wujunfeng
	 */
	private Map<String, Object> parseParams(Map<String, Object> param){
		Map<String, Object> requestParam = new HashMap<String, Object>();
		if(param != null){
			requestParam.put("sex", parseValue(param.get("sex")));
			requestParam.put("root", parseValue(param.get("root")));
			requestParam.put("character_portrait_risk_rule", parseValue(param.get("portrait")));
			requestParam.put("age_rule", parseValue(param.get("age")));
			requestParam.put("linkman_black_list_rule", parseValue(param.get("contactForbidenPercent")));
			requestParam.put("card_area_limit_rule", IdCarUtils.getProvinceByIdCard(StrUtil.utf8Str(param.get("cardNo"))));
			requestParam.put("collect_phone_num_rule", parseValue(param.get("collectionTimes")));
			requestParam.put("overdue_num_rule", parseValue(param.get("overduePlatCount")));
			requestParam.put("length_of_access_rule", parseValue(param.get("in_time")));
			requestParam.put("address_book_num_rule", parseValue(param.get("contactNum")));
			requestParam.put("short_message_model_score_rule", parseValue(param.get("msgScore")));
			requestParam.put("agency_score", parseValue(param.get("agencyScore")));
			requestParam.put("direct_linkman_black_num", parseValue(param.get("directLinkmanBlackNum")));
			requestParam.put("indirect_linkman_black_num", parseValue(param.get("indirectLinkmanBlackNum")));
			requestParam.put("direct_cause_indirect_rate", parseValue(param.get("directCauseIndirectRate")));
			requestParam.put("direct_linkman_num", parseValue(param.get("directLinkmanNum")));
			requestParam.put("cause_direct_linkman_num", parseValue(param.get("causeDirectLinkmanNum")));
			requestParam.put("searched_org_cnt", parseValue(param.get("searchedOrgCnt")));
			requestParam.put("register_org_cnt", parseValue(param.get("registerOrgCnt")));
			requestParam.put("idcard_with_other_names", parseValue(param.get("idcardWithOtherNames")));
			requestParam.put("idcard_with_other_phones", parseValue(param.get("idcardWithOtherPhones")));
			requestParam.put("phone_with_other_idcards", parseValue(param.get("phoneWithOtherIdcards")));
			requestParam.put("phone_with_other_names", parseValue(param.get("phoneWithOtherNames")));
			requestParam.put("msg_num", parseValue(param.get("msgCount")));
			requestParam.put("location_num", parseValue(param.get("locationNum")));
			requestParam.put("actual_loan_platform_count", parseValue(param.get("actualLoanPlatformCount")));
			requestParam.put("actual_loan_platform_count_1m", parseValue(param.get("actualLoanPlatformCount1m")));
			requestParam.put("actual_loan_platform_count_3m", parseValue(param.get("actualLoanPlatformCount3m")));
			requestParam.put("actual_loan_platform_count_6m", parseValue(param.get("actualLoanPlatformCount6m")));
			requestParam.put("loan_platform_count", parseValue(param.get("loanPlatformCount")));
			requestParam.put("loan_platform_count_1m", parseValue(param.get("loanPlatformCount1m")));
			requestParam.put("loan_platform_count_3m", parseValue(param.get("loanPlatformCount3m")));
			requestParam.put("loan_platform_count_6m", parseValue(param.get("loanPlatformCount6m")));
			requestParam.put("repayment_platform_count", parseValue(param.get("repaymentPlatformCount")));
			requestParam.put("repayment_platform_count_1m", parseValue(param.get("repaymentPlatformCount1m")));
			requestParam.put("repayment_platform_count_3m", parseValue(param.get("repaymentPlatformCount3m")));
			requestParam.put("repayment_platform_count_6m", parseValue(param.get("repaymentPlatformCount6m")));
			requestParam.put("repayment_times_count", parseValue(param.get("repaymentTimesCount")));
			requestParam.put("mobile_count", parseValue(param.get("mobileCount")));
			requestParam.put("link_user_count", parseValue(param.get("linkUserCount")));
			requestParam.put("other_link_device_count", parseValue(param.get("otherLinkDeviceCount")));
			requestParam.put("user_have_bankcard_count", parseValue(param.get("userHaveBankcardCount")));
			requestParam.put("partner_user_count", parseValue(param.get("partnerUserCount")));
			requestParam.put("bankcard_count", parseValue(param.get("bankcardCount")));
			requestParam.put("link_device_count", parseValue(param.get("linkDeviceCount")));
			requestParam.put("other_frand_device_count", parseValue(param.get("otherFrandDeviceCount")));
			requestParam.put("other_living_attack_device_count", parseValue(param.get("otherLivingAttackDeviceCount")));
			requestParam.put("frand_device_count", parseValue(param.get("frandDeviceCount")));
			requestParam.put("living_attack_device_count", parseValue(param.get("livingAttackDeviceCount")));
			// 这个参数要特殊处理
			requestParam.put("user_feature_6", 0);
			requestParam.put("user_feature_5", 0);
			requestParam.put("user_feature_7", 0);
			requestParam.put("user_feature_0", 0);
			requestParam.put("user_feature_21", 0);
			requestParam.put("user_feature_2", 0);
			requestParam.put("user_feature_18", 0);
			requestParam.put("user_feature_10", 0);
			requestParam.put("user_feature_11", 0);
			requestParam.put("user_feature_23", 0);
			requestParam.put("user_feature_8", 0);
			String userFeatureType = StrUtil.utf8Str(param.get("userFeatureType"));
			if(StrUtil.isNotBlank(userFeatureType)){
				List<String> userFeatureTypes = Arrays.asList(userFeatureType.split(","));
				for (String userFeature : userFeatureTypes) {
					requestParam.put("user_feature_" + userFeature, 1);
				}
			}
		}
		return requestParam;
	}
	
	/**
	 * 把object转String 或对应的数值类型,如果值为null，默认-99
	 * @param value
	 * @return
	 * @author:wujunfeng
	 */
	private Object parseValue(Object value){
		String valueStr = StrUtil.nullToDefault(StrUtil.utf8Str(value), "-99");
		try {
			//数字类型需要转换
			if(NumberUtil.isNumber(valueStr)){
				return NumberUtil.parseNumber(valueStr);
			}
		} catch (Exception e) {
			MarvelsLogUtil.getInstance().error("风险模型值转换异常", e);
		}
		return valueStr;
	}
}
